#include "qpainterwidget.h"
#include "ui_qpainterwidget.h"

QpainterWidget::QpainterWidget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::QpainterWidget)
{
    ui->setupUi(this);
   // setPalette(QPalette(Qt::white));   //设置窗口为白色背景
  //  setAutoFillBackground(true);       //设定背景时一定要设置setAutoFillBackground
}

QpainterWidget::~QpainterWidget()
{
    delete ui;
}
/*
一.基本绘图属性
1.基本绘图类：
Qt的绘图功能基于QPainter、QPainterDevice和QPainterEngine三个类。QPainter类在窗口和其他绘制设备上执行低级绘制。
它提供高度优化的功能来完成大多数图形用户界面程序所需的工作，包括绘制基本的点、线、圆等基本形状，以及复杂的形状如饼图和弦等。
此外，QPainter还能绘制对齐的文本和像素图。
QPaintDevice类表示QPainter的绘图设备，QPainter能在QPaintDevice的子类上进行图形绘制，
QpaintDevice子类包含QImage、QOpenGLPaintDevice、QWidget、QPixmap、PixelBuffer、QGLFramebufferObject、QPicture、QPrinter。

2.绘图事件：
void wiget::paintEvent(QPaintEvent *event){}
QPainter只能在paintEvent中进行绘图。paintEvent事件在窗口刷新时触发，如最大化最小化，拖动窗口边缘时也会触发。

3.主要属性：

(1) QPen：控制线条颜色宽度线性。
(2) QBrush：设置一个区域的填充特性。
(3) QFont：用于绘制文字。
(4) QPixmap: 绘制图片，适合小图片。
(5) QImage: 绘制图片，适合大图片。
(6) QBitmap: QPixmap的一个子类，单通道图。
(7) QPicture: 一张画布，可以用于保存、读取Qpainter的绘图。
(8) QPrinter类是一个在打印机上绘制的绘图设备。它允许你将图形输出到打印机，生成打印预览，或者直接生成PDF文件。

4.基本图形绘制函数：
drawPoint() //画点
drawLine() //画直线
drawRect() //画矩形
drawArc() //画圆弧
drawEllipse() //画椭圆
drawPie() //画扇形
drawPolygon() //画多边形
drawChord() //画弦
drawRoundedRect() //画圆角矩形
drawPolyline() //画折线
drawConvexPolygon() //画凸多边形

二．重点绘图属性类介绍
1.QFont的一些属性与功能：
QFont是Qt框架中用于描述字体属性的工具类。
设置属性：
void setFamily(const QString &family);
void setPointSize(int size);
void setWeight(int weight);
void setItalic(bool italic);
void setUnderline(bool underline);

获取属性：
QString family() const;
int pointSize() const;
int weight() const;
bool italic() const;
bool underline() const;

2.QPen的一些属性与功能：
主要函数：
//函数原型 功能
void setColor(QColor &color) //设置画笔颜色
void setWidth(int width) //设置线条宽度
void setStyle(Qt::PenStyle style) //设置线条样式，参数为Qt::PenStyle枚举类型
void setCapStyle(Qt::PenCapStyle style) //设置线条端点样式，参数为Qt::PenCapStyle枚举类型
void setJoinStyle(Qt::PenJoinStyle style)//设置连接样式，参数为Qt::PenJoinStyle枚举类型
属性修改后，需要使用setPen()来应用于绘图。
（1）线条样式：
Qt::NoPen //没有画笔，设置此属性时，用画笔不会画出任何东西。但是画刷仍然有效，表现出来就是无边界，但有填充。
Qt::SolidLine //实线
Qt::DashLine //虚线
Qt::DotLine //点状线
Qt::DashDotLine //虚线和点交替
Qt::DashDotDotLine //虚线和双点交替
Qt::CustomDashLine //自定义样式
（2）线条端点样式：
Qt::FlatCap //平顶端点
Qt::SquareCap //方形端点
Qt::RoundCap //圆形端点
（3）线条连接样式：
Qt::BevelJoin //斜切连接
Qt::MiterJoin //直角连接
Qt::RoundJoin //圆连接

3.QBrush的一些属性与功能：
主要函数：
//函数原型 功能
void setColor(QColor &color) //设置画刷颜色
void setStyle(Qt::BrushStyle style) //设置画刷样式
void setTexture(QPixmap &pixmap) //设置一个QPixmap图片作为画刷的图片
void setTextureImage(QImage &image) //设置一个QImage类型的图片作为画刷的图片

（1）基本填充和线性填充：
//枚举常量 描述
Qt::NoBrush //不填充
Qt::SolidPattern //单一颜色填充
Qt::HorPattern //水平线填充
Qt::VerPattern //垂直线填充

（2）渐变填充：
Qt::LinearGradientPattern //线性渐变，需要使用QLinearGradient类对象作为Brush
Qt::RadialGradientPattern //辐射渐变，需要使用QRadialGradient类对象作为Brush
Qt::ConicalGradientPattern //圆锥型渐变，需要使用QConicalGradient类对象作为Brush
Qt::TexturePattern //材质填充，需要指定texture或textureImage图片

4. QPrinter用法
（1）QPrinter printer;
printer.setOutputFormat(QPrinter::PdfFormat); // 设置输出格式为PDF，也可以其他格式
printer.setOutputFileName("output.pdf"); // 设置输出文件名
QPainter painter1(&printer);
painter1.drawText(100, 100, "Hello, PDF1!");
painter1.end(); // 结束绘制，内容将被发送到打印机

（2）注意：
用QPrinter需要添加QT += printsupport；
当设置QPainter painter1(&printer)后，绘制图形输出到pdf文件，就不会再输出到ui页面上了。
*/
//界面刷新时会触发paint事件，如最大化最小化、拖动窗口边缘时也会触发
void QpainterWidget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);

    //画线
    painter.drawLine(QPoint(0,0),QPoint(100,100));

    //创建画笔
    QPen pen(Qt::green,5,Qt::DotLine,Qt::RoundCap,Qt::RoundJoin);

    painter.setPen(pen);
    //QRectF类使用浮点精度定义平面中的矩形
    QRectF rectangle(70.0,40.0,80.0,60.0);
    int startAngle=30*16;
    int spanAngle=120*16;
    //画弧线  startAngle和spanAngle必须指定为1/16度，即一个完整的圆等于5760（16*360）。角度的正值表示逆时针方向，负值表示顺时针方向。零度位于3点钟位置。
    painter.drawArc(rectangle,startAngle,spanAngle);

    pen.setWidth(1);
    pen.setStyle(Qt::SolidLine);
    painter.setPen(pen);
    //绘制一个矩形  //和数学中的坐标轴一致水平向右为X轴 垂直向下为Y轴
    painter.drawRect(160,20,50,40);

    //创建画刷
    QBrush brush(QColor(0,0,255),Qt::Dense4Pattern);

    //使用画刷
    painter.setBrush(brush);

    //绘制椭圆
    /* void QPainter::drawEllipse(int x, int y, int width, int height)
     * 这是一个重载函数。绘制由矩形定义的椭圆，矩形从（x，y）开始，具有给定的宽度和高度
    */
   // painter.drawEllipse(220,20,50,50); //画半径为25的圆
    painter.drawEllipse(220,20,70,50); //画长半轴是35短半轴是25的椭圆
    //设置纹理
    brush.setTexture(QPixmap("abc.png"));

    //重新使用画刷
    painter.setBrush(brush);

    //定义四个点
    static const QPointF points[4]={

    QPointF(270.0,80.0),//左下角点坐标

    QPointF(290.0,10),  //左上角点

    QPointF(350.0,30),  //右边上角点坐标

    QPointF(360.0,50)   //右下角点坐标

    };
    //画多边形
    painter.drawPolygon(points,4);


    /*
     * void QPainter::fillRect(int x, int y, int width, int height, const QBrush &brush)
     * 使用指定的笔刷填充给定的矩形。
      或者，您可以指定一个QColor而不是QBrush；QBrush构造函数（采用QColor参数）将自动创建一个实心图案笔刷
    */
    painter.fillRect(QRect(10,100,150,20),QBrush(Qt::darkYellow));  //用很黄色以（10，100）为起始点画宽150高20的矩形

    painter.eraseRect(QRect(50,80,50,120));/*擦除给定矩形内的区域。相当于调用 fillRect(rectangle, background()).*/

    //线性渐变
    /*
    QLinearGradient类与QBrush组合使用以指定线性渐变笔刷。
    线性渐变在起点和终点之间插入颜色。在这些点之外，根据当前设置的排列方法，渐变或被填充、或反射或重复：
    */
    QLinearGradient linearGradient(QPointF(40,190),QPointF(70,190));

    //1)插入颜色
    linearGradient.setColorAt(0,Qt::yellow);
    linearGradient.setColorAt(0.5,Qt::red);
    linearGradient.setColorAt(1.0,Qt::green);

    //2)指定渐变区域以外的区域的扩散方式
    /*
    QGradient::RepeatSpread-- 渐变在渐变区域外重复
    QGradient::ReflectSpread--渐变反映在渐变区域之外。
    QGradient::PadSpread---该区域填充有最接近的停止颜色。这是默认设置。
    */
    linearGradient.setSpread(QGradient::RepeatSpread);

    //3)使用渐变作为画刷
    painter.setBrush(linearGradient);
    //4)绘制图形
    painter.drawRect(10,170,90,40);

    /*
     * QColor类提供基于RGB、HSV或CMYK值的颜色。
       颜色通常根据RGB（红色、绿色和蓝色）成分指定，但也可以根据HSV（色调、饱和度和值）和CMYK（青色、品红色、黄色和黑色）成分指定。
       此外，可以使用颜色名称指定颜色。颜色名称可以是SVG 1.0的任何颜色名称。
       QColor构造函数基于RGB值创建颜色。要基于HSV或CMYK值创建QColor，请分别使用toHsv（）和toCmyk（）函数。这些函数使用所需格式返回颜色的副本。此外，静态fromRgb（）、fromHsv（）和fromCmyk（）函数根据指定值创建颜色。或者，可以使用convertTo（）函数（以所需格式返回颜色的副本）或setRgb（）、setHsv（）和setCmyk（）函数中的任何一个更改颜色的格式，将颜色转换为三种格式中的任意一种。spec（）函数告诉如何指定颜色。
       可以通过向setNamedColor（）函数传递RGB字符串（如“#1112233”）、ARGB字符串（如”#ff112233“）或颜色名称（如”blue“）来设置颜色。颜色名称取自SVG 1.0的颜色名称。name（）函数以“#RRGGBB”的格式返回颜色的名称。也可以使用setRgb（）、setHsv（）和setCmyk（）设置颜色。要获得较浅或较深的颜色，请分别使用lighter（）和darker（）函数。
       isValid（）函数指示QColor是否合法。例如，RGB值超出范围的RGB颜色是非法的。出于性能原因，QColor大多忽略非法颜色，因此，使用无效颜色的结果是未定义的。
       颜色分量可以单独检索，例如使用红色（）、色调（）和青色（）。还可以使用getRgb（）、getHsv（）和getCmyk（）函数一次性检索颜色分量的值。使用RGB颜色模型，还可以使用RGB（）访问颜色组件。
       有几个相关的非成员：QRgb是表示RGB值三元组（r，g，b）的无符号int的typdef。请注意，它还可以保存alpha通道的值（有关详细信息，请参见alpha混合图形部分）。qRed（）、qBlue（）和qGreen（）函数返回给定QRgb值的相应分量，而QRgb（）和qRgba（）函数基于给定分量值创建并返回QRgb三元组。最后，qAlpha（）函数返回所提供QRgb的alpha分量，qGray（）函数根据给定值计算并返回灰度值。
       QColor独立于平台和设备。QColormap类将颜色映射到硬件。
    */

    //辐射渐变
    /*
     * QRadialGradient类与QBrush组合使用以指定径向渐变笔刷。
      Qt同时支持简单和扩展的径向渐变。
      简单径向渐变在焦点和围绕它的圆上的端点之间插值。扩展径向渐变在焦圆和中心圆之间插值。由两个圆定义的圆锥体外部的点将是透明的。
      对于简单的径向渐变，焦点被调整为位于中心圆内，而焦点可以在扩展的径向渐变中的任何位置。
      在端点之外，根据当前设置的扩散方式，渐变会被填充、反射或重复：
      渐变中的颜色是使用QGradientStop类型的停止点定义的，即位置和颜色。使用QRadient:：setColorAt（）或QRadient：：setStops（）函数来定义停止点。
      它是渐变的一整套停止点，描述了应该如何填充渐变区域。如果没有指定停止点，则使用从0处的黑色到1处的白色的渐变。
      除了从QRadient继承的函数外，QRadialGradient类还提供了center（）、focalPoint（）和radius（）函数，分别返回渐变的中心、焦点和半径。
      QRadialGradient::QRadialGradient(const QPointF &center, qreal radius, const QPointF &focalPoint)
    */
    QRadialGradient radialGradient(QPointF(200,190),50,QPointF(275,200));

    radialGradient.setColorAt(0,QColor(255,255,100,150));

    radialGradient.setColorAt(1,QColor(0,0,0,50));

    painter.setBrush(radialGradient);

    painter.drawEllipse(QPointF(200,190),50,50);

    //锥形渐变
    /*QConicalGradient类与QBrush结合使用来指定锥形渐变笔刷。锥形渐变插值围绕中心点逆时针方向插值颜色。
     * 渐变中的颜色是使用QGradientStop类型的停止点定义的，即位置和颜色。使用QRadient:：setColorAt（）或QRadient：：setStops（）函数来定义停止点。
     * 它是渐变的一整套停止点，描述了应该如何填充渐变区域。如果没有指定停止点，则使用从0处的黑色到1处的白色的渐变。
     * 除了从QGradient继承的函数外，QConicalGradient类还提供了返回梯度的起始角度和中心的angle（）和center（）函数。
     * 请注意，setSpread（）函数对锥形渐变没有影响。原因是锥形渐变根据定义是闭合的，
     * 即锥形渐变从0到360度填充整个圆，而径向或线性渐变的边界可以分别通过其半径或最终止点指定。
    */
    QConicalGradient conicalGradient(QPointF(350,190),60);

    conicalGradient.setColorAt(0.2,Qt::cyan);

    conicalGradient.setColorAt(0.9,Qt::black);

    painter.setBrush(conicalGradient);

    painter.drawEllipse(QPointF(350,190),50,50);
#if 1
    //画笔使用线性渐变来绘制直线和文字

    painter.setPen(QPen(linearGradient,2));

    painter.drawLine(0,280,100,280);

    painter.drawText(150,280,tr("helloQt"));

    //添加文字

    QFont font1;

    font1.setPixelSize(24); //设置字体像素大小为12

    QString text="hello"; //设置显示的文本

    QFontMetrics metrics(font1); //获取文字宽度对象

    int w=metrics.width(text); //获取显示文本的宽度

    int h=metrics.height(); //获取显示文本的高度

    painter.setFont(font1);

    painter.setPen(Qt::blue);

    painter.drawText(QRect(this->width()/2-w,this->height()/2-h,w,h),text);

    //绘图打印功能

    QPrinter printer;

    printer.setOutputFormat(QPrinter::PdfFormat); // 设置输出格式为PDF，也可以设置为其他格式

    printer.setOutputFileName("output.pdf"); // 设置输出文件名

    QPainter painter1(&printer);

    painter1.drawText(100, 100, "Hello, PDF1!");

    painter1.end(); // 结束绘制，内容将被发送到打印机
#endif
}

